use winnow::combinator::{fail, separated};
use winnow::token::{take, take_while};
use winnow::{dispatch, Parser, Result};

/// 解析二进制的数
fn parse_bin_digits(input: &mut &str) -> Result<usize> {
    take_while(1.., '0'..='1')
        .try_map(|s| usize::from_str_radix(s, 2))
        .parse_next(input)
}

/// 解析八进制的数
fn parse_oct_digits(input: &mut &str) -> Result<usize> {
    take_while(1.., '0'..='7')
        .try_map(|s| usize::from_str_radix(s, 8))
        .parse_next(input)
}

/// 解析十进制的数
fn parse_dec_digits(input: &mut &str) -> Result<usize> {
    take_while(1.., '0'..='9')
        .try_map(|s| usize::from_str_radix(s, 10))
        .parse_next(input)
}

/// 解析十六进制的数
fn parse_hex_digits(input: &mut &str) -> Result<usize> {
    take_while(1.., ('0'..='9', 'A'..='F', 'a'..='f'))
        .try_map(|s| usize::from_str_radix(s, 16))
        .parse_next(input)
}

/// 解析数字
fn parse_digits(input: &mut &str) -> Result<usize> {
    dispatch!(take(2usize);
        "0b" => parse_bin_digits,
        "0o" => parse_oct_digits,
        "0d" => parse_dec_digits,
        "0x" => parse_hex_digits,
        _ => fail,
    )
    .parse_next(input)
}

fn parse_list(input: &mut &str) -> Result<Vec<usize>> {
    separated(0.., parse_digits, ",").parse_next(input)
}


fn main() {
    let mut input = "0x1a2b,0x3c4d,0x5e6f Hello";

    let digits = parse_list.parse_next(&mut input).unwrap();

    assert_eq!(input, " Hello");
    assert_eq!(digits, vec![0x1a2b, 0x3c4d, 0x5e6f]);

    assert!(parse_digits(&mut "ghiWorld").is_err());
}
